;(function($){
	// define TCTree
	$.Tree=$.Widget.extend({
		/*("hasNext"|"end")+("hasChild"|"noChild")+("expand"|"fold")*/
		styles:{F:'icon_folder',LEAF:'icon_leaf',B:'icon_blank',A:'icon_A',AL:'icon_A_L',AT:'icon_A_T',S:'icon_S',SL:'icon_S_L',ST:'icon_S_T',T:'icon_T',L:'icon_L',I:'icon_I',NAME:'nodeText',CK0:'icon_check0',CK1:'icon_check1',CK2:'icon_check2',SELECTED:'tree-node-selected'}
		,appenableClass:{'icon_A_T':['icon_S_T',{'display':''}],'icon_A_L':['icon_S_L',{'display':''}],'icon_S_T':['icon_A_T',{'display':'none'}],'icon_S_L':['icon_A_L',{'display':'none'}]}
		,icons: {hhe:'icon_S_T',hhf:'icon_A_T',hne:'icon_T',hnf:'icon_T',ehe:'icon_S_L',ehf:'icon_A_L',ene:'icon_L',enf:'icon_L'
				,get:function(hasNext,hasChild,expand){
					return this[(hasNext?'h':'e')+(hasChild?'h':'n')+(expand?'e':'f')];
				}}
		,init: function(treeObject){
			this.treeEl=$(treeObject.treeNode);
			this.el=this.treeEl;
			this.elHtml=$.getHtml(this.el);
			this.treeData=treeObject.treeData||[];
			this.checkable=treeObject.checkable===true?true:false;
			this.click=$.isFunction(treeObject.click)?treeObject.click:$.noop;
			this.dbclick=$.isFunction(treeObject.dbclick)?treeObject.dbclick:$.noop;
			this.treeMap=this.genTreeData(this.treeData);
			this.contextMenu=null;
			if(treeObject.contextMenu&&$.fn.popup){this.initContextMenu(treeObject.contextMenu);}
			this.selectedNode=null;
			this.dragNode=null;
		},show: function(){
			var html=this.genTreeHtml(this.treeData,this.treeMap);
			this.treeEl.empty().append(html);
			this.bind();
			return this;
		},reload: function(treeData){
			try{delete this.treeData}catch(err){}
			try{delete this.treeMap}catch(err){}
			this.treeData=treeData;
			this.treeMap=this.genTreeData(this.treeData);
			var html=this.genTreeHtml(this.treeData,this.treeMap);
			this.treeEl.empty().append(html);
			return this;
		},initContextMenu:function(menuData){
			this.contextMenu=new $.Popup(menuData.items,menuData.callback);
		},getContextMenu:function(){
			return this.contextMenu;
		},setContextMenu:function(menu){
			this.contextMenu=menu?menu:this.contextMenu; return this;
		},bind: function(){
			this.treeEl.disableSelection();
			if(this.contextMenu){
				this.treeEl.bind($.browser.opera&&document.body.oncontextmenu?'mousedown':'contextmenu',this,function(event){
					var tree=event.data;
					tree.getContextMenu().show(event);
					return !tree.getContextMenu().getEl().is(':visible');
				});
			}
			this.treeEl.bind('dbclick',this,function(event){
				var tree=event.data;
				var treeId=el.parents('.treeRow:first').attr('treeId');
				tree.dbclick.call(tree,tree.treeMap[treeId],event);
			});
			this.treeEl.bind('click',this,function(event){
				var el=$(event.srcElement||event.target);
				var elclass=el.get(0).className;
				var tree=event.data;
				var check=tree.isCheckable()?tree.check(el):false;
				var selection=tree.selectNode(el,elclass);
				if(!check){
					var en = tree.getExpandNode(el);
					if(en){tree.expand(en);}
				}
				if(selection){
					var treeId=el.parents('.treeRow:first').attr('treeId');
					var data=null;try{data=tree.treeMap[treeId];}catch(err){}
					tree.click.call(tree,data,event);
				}
			});
			this.treeEl.bind('mousedown',this,function(event){
				var $el=$(event.srcElement||event.target);
				var tree=event.data;
				var p=$el.parent().is('.treeNode')?$el.parent().children('.EN:first'):null;
				if(p){
					tree.dragger(null);
					tree.getEl().removeData('mousedown');
					var pos=$el.position();
					var of=$el.offset();
					tree.getEl().data('mousedown',{el:p,pos:{top:pos.top-of.top+$(document.body).scrollTop(),left:pos.left-of.left+$(document.body).scrollLeft()}});
					$('#test1').val('top:'+pos.top+',left:'+pos.left+',clientY:'+event.clientY+',clientX:'+event.clientX+',offsetTop:'+of.top+',offsetLeft:'+of.left);
					return false;
				}
			});
			this.treeEl.bind('mousemove',this,function(event){
				var $el=$(event.srcElement||event.target);
				var tree=event.data;
				var dragData=tree.getEl().data('mousedown');
				if(dragData){
					var shadow=tree.dragger();
					if(!shadow){
						tree.dragger($('<span class="treeNode dragable"></span>').append(dragData.el.nextAll().clone()).appendTo(tree.getEl()));
						shadow=tree.dragger();
					}
					if($el.parent().hasClass('treeNode')){
						tree.selectNode($el);
						shadow.addClass('enableDrop');
					}else if($el.parent().hasClass('treeRow')){
						$('#test1').val($el.parent().html());
					}else{
						shadow.removeClass('enableDrop');
					}
					var pos = shadow.position();
					shadow.css({top:(event.clientY+dragData.pos.top+5)+'px',left:(event.clientX+dragData.pos.left+5)+'px'});
				}
			});
			this.treeEl.bind('mouseup',this,function(event){
				var $el=$(event.srcElement||event.target);
				var tree=event.data;
				var shadow=tree.dragger();
				tree.dragger(null);
				tree.getEl().removeData('mousedown');
			});
		},check: function($el){
			if($el.hasClass(this.styles.CK0)){
				$el.removeClass(this.styles.CK0).addClass(this.styles.CK2);
			}else if($el.hasClass(this.styles.CK1)){
				$el.removeClass(this.styles.CK1).addClass(this.styles.CK2);
			}else if($el.hasClass(this.styles.CK2)){
				$el.removeClass(this.styles.CK2).addClass(this.styles.CK0);
			}else{
				return false;
			}
			return true;
		},isCheckable: function(){
			return this.checkable;
		},getExpandNode: function($el){
			//var p=$el.parent();if(p.hasClass('treeNode')){var c=p.children('.EN');if(c.size()>0){return c;}}
			if($el.hasClass('icon_S_T')||$el.hasClass('icon_A_T')||$el.hasClass('icon_S_L')||$el.hasClass('icon_A_L')){
				return $el;
			}
			return null;
		},isExpand: function($el){
			return $el.hasClass(this.styles.ST)||$el.hasClass(this.styles.SL);
		},dragger: function($el){
			if($el===null||$el){
				if(this.dragNode){this.dragNode.remove();}
				this.dragNode=$el;
			}
			return this.dragNode;
		},expand: function($el){
			var icon;
			var result=0;
			if(!$el||$el.size()==0){
			}else if($el.hasClass(this.styles.AT)){
				icon=this.styles.AT;
				result=-1;
			}else if($el.hasClass(this.styles.AL)){
				icon=this.styles.AL;
				result=-2;
			}else if($el.hasClass(this.styles.ST)){
				icon=this.styles.ST;
				result=1;
			}else if($el.hasClass(this.styles.SL)){
				icon=this.styles.SL;
				result=2;
			}
			if(result){
				$el.parent().next(".subTree").css(this.appenableClass[icon][1]);
				$el.removeClass(icon).addClass(this.appenableClass[icon][0]);
			}
			return result;
		},selectNode: function($el){
			var elclass=arguments[1]||$el.get(0).className;
			var selection=null;
			if(elclass.indexOf(this.styles.F)>-1){
				selection=$el.next('.'+this.styles.NAME);
			}else if(elclass.indexOf(this.styles.NAME)>-1){
				selection=$el;
			}
			if(selection){
				if(this.selectedNode){
					this.selectedNode.removeClass('tree-node-selected');
				}
				selection.addClass('tree-node-selected');
				this.selectedNode=selection;
			}
			return selection;
		},getSelected: function(){
			var treeId=this.getEl().find('.tree-node-selected:first').parents('.treeRow:first').attr('treeId');
			try{return this.treeMap[treeId];}catch(err){}
			return null;
		},getEl: function(){
			return this.treeEl;
		},getData: function(){
			return this.treeData;
		},getTreeMap: function(){
			return this.treeMap;
		},genTreeData: function(treeData,treeMap,parentId){
			var me = arguments.callee;
			var data=treeMap||{};
			var tree=treeData||[];
			parentId=parentId||0;
			for(var i=0;i<tree.length;i++){
				data[tree[i].id]=tree[i];//{parentId:,expand:是否展开,checkable:是否可选,checkValue:是否选择,isLeaf:是否子结点,data:原数据}
				me(tree[i].children,data,tree[i].id);
			}
			return data;
		},genTreeHtml: function(treeData,treeMap,id,treeIcons,hasNext,hasChild,expand){
			var html='';
			if(!treeData){return html;}
			if(!treeMap){return html;}
			var data = treeData;
			var icons=this.icons;
			treeIcons=treeIcons||'';
			if(id==undefined||id==null){}else{
				data=(treeMap[id]||{}).children||[];
				treeIcons=treeIcons.concat('<button class="',hasNext?'icon_I':'icon_blank',' EN"></button>');
			}
			for(var i=0;i<data.length;i++){
				var owerIcon=''.concat('<button class="',icons.get(i<data.length-1,(data[i].children||[]).length>0,data[i].expand),' EN"></button>');
				var nodes=this.genTreeHtml(data[i].children,treeMap,data[i].id,treeIcons,i<data.length-1,(data[i].children||[]).length>0,data[i].expand);
				var nodeIcon=''.concat(data[i].icon?('<button class="'+data[i].icon+'"></button>'):(data[i].isLeaf?'<button class="icon_leaf"></button>':'<button class="icon_folder"></button>'));
				html=html.concat('<div treeId="',data[i].id,'" class="treeRow"><span class="treeNode"><span class="treeIndent">',treeIcons,'</span>',owerIcon,nodeIcon,this.isCheckable()?'<button class="icon_check0 CA"></button>':'','<span class="nodeText">',data[i].text,'</span></span><div class="subTree" style="display:',data[i].expand?'':'none','">',nodes,'</div></div>');
			}
			if(id==undefined||id==null){
				//append root node
				html=''.concat('<div id="',$.getIdSeed(),'" class="treeRow"><span class="treeNode"><span class="treeIndent"></span><span class="nodeText"></span></span><div class="subTree">',html,'</div></div>');
			}
			return html;
		},destroy:function(){
			$.each('click dblclick mousedown mouseup mousemove mouseover mouseout keydown keypress keyup blur focus mouseenter mouseleave change submit contextmenu'.split(' '),function($el){
				try{$el.unbind(this);}catch(err){}
			},this.treeEl);
			this.el.replaceWith(this.elHtml);
			$.removeObj(this);
		}
	});
	// end of define TCTree
})(jQuery);